package message;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;

import message.handler.BackOnlineHandler;
import message.handler.LoginHandler;
import message.handler.StatusHandler;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import comunity.Community;
import comunity.Status;
import comunity.UserInfo;

public class Login extends Packet {
	String username;
	String password;

	private static final String USERNAME_ATTRIBUTE = "username";
	private static final String PASSWORD_ATTRIBUTE = "password";
	public static final int WRONG_PASSWORD = 1;
	public static final int WRONG_USERNAME = 2;
	public static final int ALREADY_LOGGED = 3;

	public Login(String username, String password, int port, double lat, double lon) {
		super(PacketType.LOGIN, port, lat, lon);
		this.username = username;
		this.password = password;
	}

	@Override
	public String toXML() {
		Document doc = null;
		try {
			doc = super.createXMLDocument();
		} catch (ParserConfigurationException e1) {
			e1.printStackTrace();
		}

		Element root = doc.createElement(rootElementTag());
		doc.appendChild(root);
		root.setAttribute(USERNAME_ATTRIBUTE, username);
		root.setAttribute(PASSWORD_ATTRIBUTE, password);
		
	    Element connectionElement = super.createConnectionElement(doc);
	    root.appendChild(connectionElement);

		String result = null;
		try {
			result = super.generateString(doc);
		} catch (TransformerFactoryConfigurationError | TransformerException e) {
			e.printStackTrace();
		}
		return result;
	}

	@Override
	String rootElementTag() {
		return PacketType.LOGIN.toString();
	}

	public static Login createLogin(String xmlString) {
		Document doc = Packet.createXMLDocumentFromString(xmlString);

		NodeList list = doc.getElementsByTagName(PacketType.LOGIN.toString());
		Node rootNode = list.item(0);
		Node connectionNode = rootNode.getFirstChild();

		NamedNodeMap rootAttributes = rootNode.getAttributes();
		NamedNodeMap connectionAttributes = connectionNode.getAttributes();

		return new Login(rootAttributes.getNamedItem(USERNAME_ATTRIBUTE).getNodeValue(),
				rootAttributes.getNamedItem(PASSWORD_ATTRIBUTE).getNodeValue(),
				Integer.parseInt(connectionAttributes.getNamedItem(Packet.PORT_ATTRIBUTE).getNodeValue()),
				Double.parseDouble(connectionAttributes.getNamedItem(Packet.LAT_ATTRIBUTE).getNodeValue()),
				Double.parseDouble(connectionAttributes.getNamedItem(Packet.LON_ATTRIBUTE).getNodeValue())
				);
	}

	public String getUsername() {
		return username;
	}

	public String getPassword() {
		return password;
	}

	@Override
	public String getReceiver() {
		return this.getUsername();
	}

	@Override
	public int handlePacket(String address) {
		Community community = Community.obtainCommunity();

		UserInfo userInfo = new UserInfo(Status.ONLINE, this.getUsername(),
				this.getPassword(),/* address, this.getPort(),*/ this.getLat(),
				this.getLon());

		if (!community.contains(userInfo))
			return Login.WRONG_USERNAME;
		if (!community.checkPassword(this.getUsername(), this.getPassword()))
			return Login.WRONG_PASSWORD;
		boolean isNewUser = community.isNewUser(this.getUsername());
		if (community.getUserStatus(this.getUsername()) != Status.OFFLINE
				&& !isNewUser)
			return Login.ALREADY_LOGGED;

		community.setNewUser(userInfo.getUsername(), false);
		community.setUserStatus(this.getUsername(), Status.ONLINE);
		community.setUserGPSLocation(this.getUsername(), this.getLat(), this.getLon());
		
		new Thread(new LoginHandler(this.getUsername())).start();
		new Thread(new StatusHandler(this.getUsername(), Status.ONLINE))
				.start();
		new Thread(new BackOnlineHandler(this.getUsername())).start();

		return Packet.OK;
	}
}
